home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / comm / tcp / rxsocket.lha / rxsocket / examples / ping.rexx < prev    next >
OS/2 REXX Batch file  |  2000-11-28  |  4KB  |  169 lines

  1. /*
  2.     This code is NOT from Berkley, but FROM ME :-)
  3.     Very stupid Arexx ping.
  4.     Don't use it to ping localhost or you would ROTFL.
  5.  
  6.     Usage: ping <HOST> [SIZE/N] [NUM/N] [QUICK/S]
  7.  
  8.     HOST     the host name to ping
  9.      SIZE    the size of the imcp echo packet
  10.     NUM        the number of packet to send - 0 means continuos
  11.     QUICK    don't delay, send fast
  12. */
  13.  
  14. l="rmh.library";if ~show("L",l) then;if ~addlib(l,0,-30) then exit
  15. if AddLibrary("rexxsupport.library","rxsocket.library")~=0 then exit
  16.  
  17. prg = ProgramName("NOEXT")
  18.  
  19. /** read and parse arguments **/
  20. if ~RMH_ReadArgs("HOST/A,SIZE/K/N,NUM/K/N,QUICK/S") then do
  21.     call PrintFault(IoErr(),prg)
  22.     exit
  23. end
  24.  
  25. addr = resolve(parm.0.value)
  26. if addr=="-1" then call err "no host <"parm.0.value">"
  27.  
  28. host=parm.0.value
  29. if parm.1.flag then
  30.     if parm.1.value>7 & parm.1.value<8000 then dataSize=parm.1.value
  31.     else call err("SIZE must be >7 and <8000")
  32. else dataSize=56
  33.  
  34. if parm.2.flag then
  35.     if parm.2.value>0 then numPkt=parm.2.value
  36.     else call err("NUM must be positive")
  37. else numPkt=1E10
  38.  
  39. wait=~parm.3.flag
  40.  
  41. break=0
  42. signal on BREAK_C
  43.  
  44. /** resolve host name **/
  45. sin.addrAddr=resolve(host)
  46. if sin.addrAddr=="-1" then call err("HOST not found")
  47.  
  48. /** create a RAW ICMP socket **/
  49. sock=socket("INET","RAW","ICMP")
  50. if sock<0 then call err("no socket")
  51.  
  52. /** socket must NOT blocking **/
  53. call IOCtlSocket(sock,"FIONBIO",1)
  54.  
  55. /** we need an ID to recognize our icmp **/
  56. ourID=right(x2c(pragma("ID")),2)
  57. min=1E10
  58. max=0
  59. avg=0
  60. nrec=0
  61. ntrans=0
  62.  
  63. /** create a timer **/
  64. t=CreateTimer()
  65. timSig=TimerSignal(t)
  66.  
  67. if numPkt==1E10 then ps=""
  68. else ps=" Num:" numPkt
  69. say Upper(PRG) host "("sin.addrAddr"):" dataSize "data bytes" ps
  70.  
  71. /** we go:
  72.     wait_for_packet_or_time_to_send
  73.     readpacket if any
  74.     sendpacket if time
  75. **/
  76. call StartTimer(t,wait)
  77. call sendPacket(dataSize)
  78. sel.read.0=sock
  79. go=ntrans<numPkt | numPkt==1
  80. do while go
  81.  
  82.     res=WaitSelect("SEL",,,timSig)
  83.     if res~=0 then call readPacket
  84.  
  85.     if and(sel.signals,timSig)~=0 then do
  86.         call sendPacket(dataSize)
  87.         if wait==0 then call WriteCH("STDOUT",".")
  88.         call StartTimer(t,wait)
  89.     end
  90.     go=ntrans<numPkt
  91. end
  92. signal BREAK_C
  93. exit
  94.  
  95. err:
  96. parse arg msg
  97.     say prg":" msg
  98.     exit
  99.  
  100. pad: PROCEDURE
  101. parse arg string,len
  102.     return copies(d2c(0),len-length(string)) || string
  103.  
  104. d2m: PROCEDURE
  105. parse arg val,len
  106.     return pad(d2c(val),len)
  107.  
  108. sendPacket:
  109. parse arg dataSize
  110.     /** here we create an ICMP echo packet **/
  111.     pktf = ourID || d2m(ntrans,2)
  112.     call GetSysTime("TV")
  113.     pktf=pktf || d2m(tv.secs,4) || d2m(tv.micro,4) || copies("0"x,dataSize-8)
  114.     temp="0800"x || "0000"x || pktf
  115.     pkt="0800"x || d2c(InetCksum(temp)) || pktf
  116.     res=SendTo(sock,pkt,0,"SIN")
  117.     if res~=length(pkt) then do
  118.         e=errno()
  119.         if IsLibOn("TTCP") then es=e
  120.         else es=ErrorString(e)
  121.         call err("send error ("es")")
  122.     end
  123.     ntrans=ntrans+1
  124.     return
  125.  
  126. readPacket:
  127.     /** here we read an ICMP packet and check if it is an ICMP
  128.         echo-replay for us **/
  129.     call GetSysTime("NOW")
  130.     res=RecvFrom(sock,"BUFF",256)
  131.     if res<0 then call err("recv error")
  132.     parse var buff vhl +1 tos +1 len +2 id +2 off +2 ttl +1 rest
  133.     hl=c2d(bitand(vhl,'F'x))*8
  134.     buff=c2x(buff)
  135.     parse var buff +hl type +2 code +2 cksum +4 id +4 seq +4 s +8 m +8 data
  136.     if c2d(len)~=dataSize+8 | type~='00' | code~='00' | id~=c2x(ourID)
  137.         then return
  138.     old.secs=x2d(s)
  139.     old.micro=x2d(m)
  140.     call SubTime("NOW","OLD")
  141.     time=now.secs*1000000+now.micro
  142.     time=time%1000"."time//1000
  143.     time=((time*100)%1)/100
  144.     if wait==1 then
  145.         say c2d(len) "bytes from" sin.AddrAddr": icmp_seq="x2d(seq) "ttl="c2d(ttl) "time="time "ms"
  146.     nrec=nrec+1
  147.     if time>max then max=time
  148.     if time<min then min=time
  149.     avg=avg+time
  150.     return
  151.  
  152. /** statistics **/
  153. BREAK_C:
  154.     if break==1 | sigl<38 then call err("user break")
  155.     if t~="T" then call StopTimer(t)
  156.     break=1
  157.     signal on BREAK_C
  158.     if ntrans>nrec & max>0 then do
  159.         res=WaitSelect("SEL",5)
  160.         if res~=0 then call readPacket
  161.     end
  162.     if ntrans==0 then loss=100
  163.     else loss=(ntrans-nrec)/ntrans*100
  164.     say
  165.     say "---" host "ping statistics ---"
  166.     say ntrans "packets transmitted," nrec "packets received," loss"% packet loss"
  167.     if nrec>0 then say "round-trip min/avg/max =" min"/"|| (((avg/nrec)*100)%1)/100 || "/"max "ms"
  168.     exit
  169.